package hello.word.m2.maven.support;

//import lombok.NonNull;
import org.jdbi.v3.sqlobject.customizer.Bind;
import org.jdbi.v3.sqlobject.customizer.BindList;
import org.jdbi.v3.sqlobject.customizer.Define;
import org.jdbi.v3.sqlobject.customizer.DefineList;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlUpdate;

import javax.annotation.Nullable;
import java.util.List;

public interface BaseDao<T> {

	//-- fuck: SFM(simple flat mapper) can not support java's primitive type ; use the wrapper class which its primitive type 
	@SqlQuery("select count(*) from <tableName>")
	long count(@Define("tableName") /*@NonNull*/ String tableName);
	
	long count();
	
    @SqlQuery("select * from <tableName> order by <idColumnName> <orderType> limit <limit>")
    List<T> internalFindAll(@Define("tableName") /*@NonNull*/ String tableName,
                            @Define("idColumnName") /*@NonNull*/ String idColumnName,
                            @Define("orderType") /*@NonNull*/ SqlOrderType orderType,
                            @Define("limit") int limit
    );

    @SqlQuery("select * from <tableName> where <conditions> order by <idColumnName> desc")
    List<T> internalFindConditions(@Define("tableName") /*@NonNull*/ String tableName,
                                   @Define("conditions") /*@NonNull*/ String conditions,
                                   @Define("idColumnName") /*@NonNull*/ String idColumnName);

    @SqlUpdate("update <tableName> set <columnName> = :value where <conditions>")
    int internalUpdateConditions(@Define("tableName") /*@NonNull*/ String tableName,
                                 @Define("columnName") /*@NonNull*/ String columnName,
                                 @Bind("value") /*@NonNull*/ Object value,
                                 @Define("conditions") /*@NonNull*/ String conditions);

    @SqlQuery("select * from <tableName> where <column> <operand> :value order by <idColumnName> desc")
    List<T> internalFind(@Define("tableName") /*@NonNull*/ String tableName,
                         @Define("column") /*@NonNull*/ String column,
                         @Bind("value") @Nullable Object value,
                         @Define("operand") /*@NonNull*/ String operand,
                         @Define("idColumnName") /*@NonNull*/ String idColumnName);

    @SqlUpdate("truncate table <tableName>")
    void truncate(@Define("tableName") /*@NonNull*/ String tableName);

    @SqlUpdate("delete from <tableName> where <idColumnName> = :id")
    int internalDelete(@Define("tableName") /*@NonNull*/ String tableName,
                       @Define("idColumnName") /*@NonNull*/ String idColumnName,
                       @Bind("id") /*@NonNull*/ Object id);

    @SqlUpdate("insert into <tableName> (<columnList>) values (<valueList>)")
    void internalInsert(@Define("tableName") /*@NonNull*/ String tableName,
                        @DefineList("columnList") /*@NonNull*/ List<String> columnList,
                        @BindList("valueList") /*@NonNull*/ List<Object> valueList);

    @SqlUpdate("update <tableName> set <columnName> = :value where <idColumnName> = :id")
    void internalUpdate(@Define("tableName") /*@NonNull*/ String tableName,
                        @Define("columnName") /*@NonNull*/ String columnName,
                        @Bind("value") @Nullable Object value,
                        @Define("idColumnName") /*@NonNull*/ String idColumnName,
                        @Bind("id") /*@NonNull*/ Object id);

    @SqlUpdate("update <tableName> set <columnName> = :value")
    int internalUpdateAll(@Define("tableName") /*@NonNull*/ String tableName,
                          @Define("columnName") /*@NonNull*/ String columnName,
                          @Bind("value") @Nullable Object value);

    enum SqlOrderType {
        ASC, DESC
    }
}
